# -*- coding: utf-8 -*-
__author__ = 'lztkdr'
__date__ = '2019/8/1 21:41'

import json,six
import numpy as np

def try_serialization_type(obj):
    try:
        json.dumps(obj)
        return True
    except:
        return False

def is_basic_type(obj):
    """
    是否是基础数据类型
    :param obj:实例对象
    :return:
    """
    return isinstance(obj, int) or isinstance(obj, float) \
           or isinstance(obj, str) or isinstance(obj, bool) \
           or isinstance(obj, list) or isinstance(obj, tuple) \
           or isinstance(obj, set) or isinstance(obj, dict)


def check_numpy_type_get(obj):
    if isinstance(obj,np.bool_):
        return bool(obj)
    elif isinstance(obj,np.integer):
        return int(obj)
    elif isinstance(obj,np.floating):
        return float(obj)
    elif isinstance(obj,np.ndarray):
        return obj.tolist()
    else:
        return obj


def attrs(o):
    """
    根据 对象的 属性与属性值 转换为字典
    :param o:实例对象
    :return:
    """
    dirs = dir(o)
    dc = dict()
    for dr in dirs:
        try:
            if not dr.startswith('_') and not dr == 'T':
                val = check_numpy_type_get(getattr(o, dr))
                if is_basic_type(val):
                    try:
                        json.dumps(val)#防止 值不能对其 json序列化的情况
                        dc[dr] = val
                    except:
                        continue
        except:
            continue
    return  dc


def print_attr(o,indent=None):
    """
    打印 对象的 所有属性与属性值
    :param o:实例对象
    :param indent:json缩进
    :return:
    """
    if is_basic_type(o):
        return json.dumps(o, ensure_ascii=False, indent=indent)
    else:
        return json.dumps(attrs(o), ensure_ascii=False, indent=indent)


def get_method(o,method):
    """
    获取 对象成员（属性或方法）
    :param o:实例对象
    :param method:方法
    :return:
    """

    if callable(method):
        return method
    elif isinstance(method, six.string_types):
        return getattr(o, method, None)

def members(o):
    """
    获取 对象的 属性与属性值 以及 没有参数的方法 和 方法执行后的值  的字典
    :param o:实例对象
    :return:
    """
    dirs = dir(o)
    dc = dict()
    for dr in dirs:
        try:
            if not dr.startswith('_') and not dr == 'T':
                # print(dr)
                method = get_method(o,dr)
                is_method_type = False
                result = None
                try:
                    if is_basic_type(method):  # 获取到的是属性
                        is_method_type = False
                        result = check_numpy_type_get(method)
                        if not try_serialization_type(result):
                            continue
                    else: #获取到的是方法
                        is_method_type = True
                        result =  check_numpy_type_get(method())
                        if not try_serialization_type(result):
                            continue
                except:
                    continue

                if not is_method_type:
                    dc[dr] = result
                else:
                    dc[dr + "()"] = result

                if is_basic_type(method):#获取到的是属性
                    try:
                        json.dumps(method)#防止 值不能对其 json序列化的情况
                        dc[dr] = method
                    except:
                        continue
                else: #获取到的是方法
                    res = method()
                    try:
                        json.dumps(res)#防止 值不能对其 json序列化的情况
                        dc[dr+"()"] = res
                    except:
                        # print(f"{dr}\t{type(res)}")
                        continue
        except:
            continue
    return dc

def print_members(o,indent=None):
    """
    打印 对象的所有属性 以及 没有参数的方法执行后的值
    :param o:实例对象
    :param indent:json缩进
    :return:
    """
    if is_basic_type(o):
        print(json.dumps(o, ensure_ascii=False, indent=indent))
    else:
        print(json.dumps(members(o), ensure_ascii=False, indent=indent))
